﻿using Abp;
using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.Dependency;
using Abp.Domain.Repositories;
using Abp.Extensions;
using Abp.Json;
using Abp.Linq.Extensions;
using Abp.UI;
using Microsoft.EntityFrameworkCore;
using Mt.Organizations;
using Mt.Site.Application.Dto;
using Mt.Site.Application.Organizations.Dto;
using Mt.Site.Application.WorkFlows.Dto;
using Mt.Site.Core.Organizations.UserCache;
using Mt.Site.Core.Organizations.UserCache.Models;
using Mt.Site.Core.WorkFlows;
using Mt.Site.Core.WorkFlows.Design;
using Mt.Site.Core.WorkFlows.Design.Cache;
using Mt.Site.Core.WorkFlows.Design.Entities;
using Mt.Site.Core.WorkFlows.Diy;
using Mt.Site.Core.WorkFlows.Diy.Plugin;
using Mt.Site.Core.WorkFlows.Enum;
using Mt.Site.Core.WorkFlows.Permissions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;

namespace Mt.Site.Application.WorkFlows.Impl
{
    [AbpAuthorize(WorkFlowPermissions.Pages_Manage_WorkFlow_Admin)]
    public class WorkFlowDesignAppService : MtSiteAppServiceBase, IWorkFlowDesignAppService
    {
        public readonly char[] SplitChars = WorkFlowConst.SplitChars.ToCharArray();

        private readonly IRepository<WorkFlowCategeory, Guid> _workFlowCategeoryRepository;
        private readonly IWorkflowDesignService _workflowDesignService;
        private readonly IRepository<WorkFlow, Guid> _workFlowRepository;
        private readonly IRepository<WorkFlowForm, Guid> _workFlowFormRepository;
        private readonly IRepository<WorkFlowNode, Guid> _workFlowNodeRepository;
        private readonly IRepository<WorkFlowPaperListCtrl, Guid> _workFlowPaperListCtrlRepository;
        private readonly IRepository<MtOrganizationUnit, long> _organizationUnitRepository;
        private readonly IUserAndUnitFinder _userAndUnitFinder;
        private readonly IIocResolver _iocResolver;
        private readonly IWorkFlowPluginConfiguration _workFlowPluginConfiguration;

        public WorkFlowDesignAppService(
            IRepository<WorkFlowCategeory, Guid> workFlowCategeoryRepository,
            IWorkflowDesignService workflowDesignService,
            IRepository<WorkFlow, Guid> workFlowRepository,
            IRepository<WorkFlowForm, Guid> workFlowFormRepository,
            IRepository<WorkFlowNode, Guid> workFlowNodeRepository,
            IRepository<WorkFlowPaperListCtrl, Guid> workFlowPaperListCtrlRepository,
            IRepository<MtOrganizationUnit, long> organizationUnitRepository,
            IUserAndUnitFinder userAndUnitFinder,
            IIocResolver iocResolver,
            IWorkFlowPluginConfiguration workFlowPluginConfiguration)
        {
            _workFlowCategeoryRepository = workFlowCategeoryRepository;
            _workflowDesignService = workflowDesignService;
            _workFlowRepository = workFlowRepository;
            _workFlowFormRepository = workFlowFormRepository;
            _workFlowNodeRepository = workFlowNodeRepository;
            _workFlowPaperListCtrlRepository = workFlowPaperListCtrlRepository;
            _organizationUnitRepository = organizationUnitRepository;
            _userAndUnitFinder = userAndUnitFinder;
            _iocResolver = iocResolver;
            _workFlowPluginConfiguration = workFlowPluginConfiguration;
        }

        #region Category

        public async Task<PagedResultDto<PagedCategoryDto>> GetPagedCategoryAsync(PagedCategoryInput input)
        {
            var query = _workFlowCategeoryRepository.GetAll()
                        .WhereIf(!string.IsNullOrWhiteSpace(input.Filter), item => item.Name.Contains(input.Filter));

            query = !string.IsNullOrWhiteSpace(input.Sorting)
                  ? query.OrderBy(input.Sorting)
                  : query.OrderByDescending(t => t.Order)
                         .ThenByDescending(t => t.CreationTime);
            var count = query.Count();
            var list = await query.PageBy(input).ToListAsync();
            var result = ObjectMapper.Map<List<PagedCategoryDto>>(list);
            foreach (var item in result)
            {
                item.WfCount = await _workFlowRepository.CountAsync(c => c.CategeoryId == item.Id);
            }
            return new PagedResultDto<PagedCategoryDto>(count, result);
        }

        public async Task CreateCategoryAsync(CreateCategoryInput input)
        {
            var entity = ObjectMapper.Map<WorkFlowCategeory>(input);
            if(entity.Order == 0)
            {
                entity.Order = await GetMaxOrderForCategory();
            }
            await _workflowDesignService.CreateCategoryAsync(entity);
        }

        public async Task UpdateCategoryAsync(UpdateCategoryInput input)
        {
            var entity = await _workFlowCategeoryRepository.FirstOrDefaultAsync(item => item.Id == input.Id);
            if (entity != null)
            {
                entity.Name = input.Name;
                entity.IsActive = input.IsActive;
                entity.Order = input.Order;
            }
            await _workflowDesignService.UpdateCategoryAsync(entity);
        }

        public async Task DeleteCategoryAsync(EntityIdListDto input)
        {
            foreach (var item in input.List)
            {
                await _workflowDesignService.DeleteCategoryAsync(item);
            }
        }

        public async Task SetStatus(SetStatusInput input)
        {
            var list = await _workFlowCategeoryRepository.GetAllListAsync(item => input.IdList.Contains(item.Id));

            foreach (var item in list)
            {
                item.IsActive = input.IsActive;
                await _workflowDesignService.UpdateCategoryAsync(item);
            }
        }

        public async Task SetNewOrderInfoAsync(NewSortNumberInput input)
        {
            var entity = await _workFlowCategeoryRepository.FirstOrDefaultAsync(item => item.Id == input.Id);
            if (entity != null)
            {
                entity.Order = input.NewNumber;
                await _workflowDesignService.UpdateCategoryAsync(entity);
            }
        
        }

        public async Task<List<FlowCategotyDto>> GetAllCategoryAsync()
        {
            var list = await _workFlowCategeoryRepository.GetAllListAsync(item => item.IsActive);
            return ObjectMapper.Map<List<FlowCategotyDto>>(list);
        }

        private async Task<int> GetMaxOrderForCategory()
        {
            var query = from q in _workFlowCategeoryRepository.GetAll()
                        orderby q.Order descending
                        select q;
            var m = await query.FirstOrDefaultAsync();
            if (m != null)
            {
                return m.Order + 1;
            }
            else
            {
                return 1;
            }
        }

        public async Task SwapCategorySortNumber(SwapSortNumberInput input)
        {
            var idList = input.IdOrderList.Select(c => c.Id).ToList();
            var orderList = input.IdOrderList.Select(c => c.Order).ToList();

            if (idList.Count == 0)
            {
                return;
            }

            var list = await _workFlowCategeoryRepository.GetAllListAsync(c => idList.Contains(c.Id));

            foreach (var item in list)
            {
                var index = idList.FindIndex(c => c == item.Id);
                if (index != -1)
                {
                    item.Order = orderList[index];
                }
            }
        }

        #endregion

        #region  workflow
        public async Task<PagedResultDto<PagedDesignDto>> GetPagedDesignAsync(PagedDesignInput input)
        {
            var query = _workFlowRepository.GetAll()
                        .WhereIf(!string.IsNullOrWhiteSpace(input.Filter), item => item.Name.Contains(input.Filter))
                        .WhereIf(input.FlowCategoryId != null,item=>item.CategeoryId == input.FlowCategoryId);

            query = !string.IsNullOrWhiteSpace(input.Sorting)
                  ? query.OrderBy(input.Sorting)
                  : query.OrderByDescending(t => t.Order)
                         .ThenByDescending(t => t.CreationTime);
            var count = await query.CountAsync();
            var list = await query.PageBy(input).ToListAsync();
            var result = ObjectMapper.Map<List<PagedDesignDto>>(list);
            foreach (var item in result)
            {
                item.PaperCount = await _workflowDesignService.CheckPapersCountAsync(item.Id);
            }

            return new PagedResultDto<PagedDesignDto>(count, result);
        }

        public async Task<GetWorkFlowForEditOutput> GetDesignAsync(NullableIdDto<Guid> input)
        {
            var functionList = new List<NameValue>();
            foreach (var item in _workFlowPluginConfiguration.WorkFlowPluginProviders)
            {
                using (var ob = _iocResolver.ResolveAsDisposable<WorkFlowPluginFunctionsBase>(item.Value))
                {
                    functionList.Add(new NameValue { Name = ob.Object.DisplayName, Value = ob.Object.UniqeName });
                }
            }

            if (input.Id.HasValue)
            {
                var entity = await _workFlowRepository.GetAsync(input.Id.Value);
                var result = ObjectMapper.Map<WorkFlowDesignDto>(entity);
                result.CustomData = (entity.CustomData.IsNullOrWhiteSpace() ? new WorkflowCustomData() : entity.CustomData.FromJsonString<WorkflowCustomData>());
                if (!entity.UnitIdList.IsNullOrWhiteSpace())
                {
                    var arr = entity.UnitIdList.Split(SplitChars, StringSplitOptions.RemoveEmptyEntries).ToList();
                    var units = await _organizationUnitRepository.GetAllListAsync(item => arr.Contains(item.Id.ToString()));
                    var names = new List<string>();
                    units.ForEach(item =>
                    {
                        if (!item.ShortName.IsNullOrWhiteSpace())
                        {
                            names.Add(item.ShortName);
                        }
                    });
                    result.UnitNames = string.Join(",", names);
                }
                return new GetWorkFlowForEditOutput
                {
                    WorkFlow = result,
                    Functions = functionList
                };
            }
            else
            {
                return new GetWorkFlowForEditOutput
                {
                    Functions = functionList,
                    WorkFlow = new WorkFlowDesignDto
                    {
                        IsActive = true,
                        Order = await GetMaxOrderForWorkflow(),
                        CustomData = new WorkflowCustomData()
                    }
                };
            }
        }

        public async Task CreateDesignAsync(CreateDesignInput input)
        {
            var entity = ObjectMapper.Map<WorkFlow>(input);
            if(entity.Order == 0)
            {
                //entity.Order = await GetMaxOrderForWorkflow();
            }
            entity.CustomData = input.CustomData.ToJsonString();

            await _workflowDesignService.CreateDesignAsync(entity);

        }
        private async Task<int> GetMaxOrderForWorkflow()
        {
            var query = from q in _workFlowRepository.GetAll()
                        orderby q.Order descending
                        select q;
            var m = await query.FirstOrDefaultAsync();
            if (m != null)
            {
                return m.Order + 1;
            }
            else
            {
                return 1;
            }
        }
        public async Task UpdateDesignAsync(UpdateDesignInput input)
        {
            var entity = await _workFlowRepository.GetAsync(input.Id);
            ObjectMapper.Map(input, entity);
            entity.CustomData = input.CustomData.ToJsonString();
            await _workflowDesignService.UpdateDesignAsync(entity);
        }

        public async Task DeleteDesignAsync(EntityIdListDto input)
        {
            foreach (var item in input.List)
            {
                await _workflowDesignService.DeleteDesignAsync(item);
            }
        }

        public async Task SetDesignStatus(SetStatusInput input)
        {
            var list = await _workFlowRepository.GetAllListAsync(item => input.IdList.Contains(item.Id));

            foreach (var item in list)
            {
                item.IsActive = input.IsActive;
                await _workflowDesignService.UpdateDesignAsync(item);
            }
        }

        public async Task SetDesignNewOrderInfoAsync(NewSortNumberInput input)
        {
            var entity = await _workFlowRepository.FirstOrDefaultAsync(item => item.Id == input.Id);
            if (entity != null)
            {
                entity.Order = input.NewNumber;
                await _workflowDesignService.UpdateDesignAsync(entity);
            }
        }

        public async Task<List<AllDesignInfosDto>> GetAllWorkFlows()
        {
            var query = from flow in _workFlowRepository.GetAll()
                        .Where(item=>item.IsHaveOnlineWord)
                        select new AllDesignInfosDto
                        {
                            Id = flow.Id,
                            Name = flow.Name,
                            ShortName = flow.ShortName
                        };
            var list = await query.ToListAsync();
            return list;


        }

        public async Task CopyWorkFlowDefinitionAsync(EntityDto<Guid> input)
        {
            await _workflowDesignService.CopyWorkFlowDefinitionAsync(input.Id);
        }
        #endregion


        #region  workFlowForm
        public async Task<WorkFlowFormDto> GetFlowFormAsync(EntityDto<Guid> input)
        {
            var entity = await _workFlowFormRepository.FirstOrDefaultAsync(item => item.WorkFlowId == input.Id);
            if (entity != null)
            {
                return ObjectMapper.Map<WorkFlowFormDto>(entity);
            }
            return null;
        }

        public async Task CreateFlowFormAsync(CreateFlowFromInput input)
        {
            var entity = ObjectMapper.Map<WorkFlowForm>(input);
            await _workflowDesignService.CreateWorkFlowFormAsync(entity);
        }

        public async Task UpdateFlowFormAsync(UpdateWorkForm input)
        {
            var entity = await _workFlowFormRepository.GetAsync(input.Id);
            entity.ExtensionData = input.ExtensionData;
            entity.HtmlData = input.HtmlData;
            entity.IsActive = input.IsActive;
            await _workflowDesignService.UpdateWorkFlowFormAsync(entity);
        }

        public async Task DeleteFlowFormAsync(EntityIdListDto input)
        {
            foreach (var item in input.List)
            {
                await _workflowDesignService.DeleteWorkFlowFormAsync(item);
            }
        }
        #endregion


        #region  workFlowNode
        private const string RemoveNodeMsg = "该流程已有稿件在流转，不能修改（修改流程定义前需删除该流程的所有在办、办结、归档的稿件）！";
        public async Task<List<PagedFlowNodeDto>> GetPagedFlowNodeAsync(PagedFlowNodeInput input)
        {
            var list = await GetAllBrotherNodes(input.WorkflowId);
            var result = new List<PagedFlowNodeDto>();
            foreach (var item in list)
            {
                var dto = ObjectMapper.Map<PagedFlowNodeDto>(item);
                dto.CanBeRemove = await _workflowDesignService.CanNodeBeRemoveOrEdit(item, list);
                result.Add(dto);
            }
            return result;
        }

        private async Task<List<WorkFlowNode>> GetAllBrotherNodes(Guid workflowId)
        {
            var query = _workFlowNodeRepository.GetAll()
              .Where(item => item.WorkflowId == workflowId);
            query = query.OrderBy(item => item.Order);
            return await query.ToListAsync();
        }

        public async Task<GetFLowNodeForEditOutput> GetFlowNodeAsync(GetFlowNodeInput input)
        {
            var list = new List<NameValue<int>>();
            foreach (OperatorFilter item in Enum.GetValues(typeof(OperatorFilter)))
            {
                list.Add(
                    new NameValue<int>(EnumHelper.GetEnumDescription(item), item.RawValue())
                    );
            }

            var functionList = new List<NameValue>();
            foreach (var item in _workFlowPluginConfiguration.WorkFlowNodePluginProviders)
            {
                using (var ob = _iocResolver.ResolveAsDisposable<WorkFlowNodePluginFunctionsBase>(item.Value))
                {
                    functionList.Add(new NameValue { Name = ob.Object.DisplayName, Value = ob.Object.UniqeName});
                }
            }

            var schemelist = new List<NameValue>();
            foreach (ActionScheme item in Enum.GetValues(typeof(ActionScheme)))
            {
                var temp = new NameValue
                {
                    Name = EnumHelper.GetEnumDescription(item),
                    Value = item.RawValue().ToString()
                };
                schemelist.Add(temp);
            }

            var post = await _userAndUnitFinder.GetAllPostAsync();

            var actions = new List<NameValue>();
            foreach (var item in _workFlowPluginConfiguration.ActionProviders.Keys)
            {
                actions.Add(new NameValue(item, item));
            }

            if (input.NodeId.HasValue)
            {
                var entity = await _workFlowNodeRepository.GetAsync(input.NodeId.Value);
                var dto = ObjectMapper.Map<FlowNodeDto>(entity);
                dto.CustomData = (entity.CustomData.IsNullOrWhiteSpace() ? new WorkflowNodeCustomData() : entity.CustomData.FromJsonString<WorkflowNodeCustomData>());
                
                var arr = new List<string>();
                if (!dto.UserIdList.IsNullOrWhiteSpace())
                {
                    arr = dto.UserIdList.Split(SplitChars, StringSplitOptions.RemoveEmptyEntries).ToList();
                    var names = UserManager.Users.Where(item => arr.Contains(item.Id.ToString())).OrderByDescending(c => c.Order).Select(item => item.Name).ToList();
                    dto.UserNames = string.Join(",", names);
                }
                return new GetFLowNodeForEditOutput
                {
                    FlowNode = dto,
                    IsHasPapers = await _workflowDesignService.IsHasPapers(entity.WorkflowId) ,
                    OperatorFilterSource = list,
                    Functions = functionList,
                    Posts = post,
                    ActionNames =actions,
                    ActionSchemeList = schemelist
                };
            }
            else
            {
                 return   new GetFLowNodeForEditOutput
                 {
                    FlowNode = new FlowNodeDto
                    {
                        IsActive = true,
                        Order =  await GetMaxOrderForWorkflowNode(input.WorkFlowId),
                        WorkflowId = input.WorkFlowId,
                        CanEditAttachment = true,
                        ActionScheme = ActionScheme.Order,
                        CustomData = new WorkflowNodeCustomData ()
                    },
                    OperatorFilterSource = list,
                    Functions = functionList,
                    Posts = post,
                    ActionNames = actions,
                    ActionSchemeList = schemelist
                 };
            }
        }

        private async Task<int> GetMaxOrderForWorkflowNode(Guid workflowId)
        {
            var query = from q in _workFlowNodeRepository.GetAll()
                        .Where(item => item.WorkflowId == workflowId)
                        orderby q.Order descending
                        select q;
            var m = await query.FirstOrDefaultAsync();
            if (m != null)
            {
                return m.Order + 1;
            }
            else
            {
                return 1;
            }
        }

        public async Task CreateFlowNodeAsync(CreateFlowNodeInput input)
        {
            var query = from q in _workFlowNodeRepository.GetAll()
                        .Where(item=>item.WorkflowId == input.WorkflowId)
                        orderby q.Order descending
                        select q;
            var m = query.FirstOrDefault();

            int order;
            if (m != null)
            {
                order = m.Order + 1;
            }
            else
            {
                order = 1;
            }

            var entity = ObjectMapper.Map<WorkFlowNode>(input);
            if(entity.Order == 0)
            {
                entity.Order = order;
                entity.CustomData = input.CustomData.ToJsonString();
            }
            await _workflowDesignService.CreateWorkFlowNodeAsync(entity);
        }

        public async Task UpdateFlowNodeAsync(UpdateFlowNodeInput input)
        {
            var entity = await _workFlowNodeRepository.FirstOrDefaultAsync(item => item.Id == input.Id);

            if (entity != null)
            {
                var allBrothers = await GetAllBrotherNodes(entity.WorkflowId);

                if ((input.IsActive == false && entity.IsActive) 
                    || CheckIsTracksChanged(entity.NextNodeList, input.NextNodeList, allBrothers)
                    || CheckIsTracksChanged(entity.BackNodeList, input.BackNodeList, allBrothers)
                    )
                {
                    if (await _workflowDesignService.CanNodeBeRemoveOrEdit(entity, allBrothers))
                    {
                        ObjectMapper.Map(input, entity);
                        entity.CustomData = input.CustomData.ToJsonString();
                    }
                    else
                    {
                        throw new UserFriendlyException(RemoveNodeMsg);
                    }
                }
                else
                {
                    ObjectMapper.Map(input, entity);
                    entity.CustomData = input.CustomData.ToJsonString();
                }
            }
        }

        private bool CheckIsTracksChanged(string oldStr, string newStr, List<WorkFlowNode> allBrothers)
        {
            if(oldStr.IsNullOrEmpty() && newStr.IsNullOrEmpty())
            {
                return false;
            }
            if (oldStr == newStr)
            {
                return false;
            }

            List<string> aa, bb;
            if (oldStr.IsNullOrEmpty())
            {
                aa = new List<string>();
            }
            else
            {
                aa = oldStr.Split(SplitChars, StringSplitOptions.RemoveEmptyEntries)
                    .Where(c=> allBrothers.FirstOrDefault(d=>d.Id.ToString().ToLower() == c)!= null)
                    .ToList();
            }
            if (newStr.IsNullOrEmpty())
            {
                bb = new List<string>();
            }
            else
            {
                bb = newStr.Split(SplitChars, StringSplitOptions.RemoveEmptyEntries)
                    .Where(c => allBrothers.FirstOrDefault(d => d.Id.ToString().ToLower() == c) != null)
                    .ToList();
            }

            if (aa.Count != bb.Count)
            {
                return true;
            }
            foreach (var item in aa)
            {
                if (!bb.Contains(item))
                {
                    return true;
                }
            }
            return false;
        }

        public async Task DeleteFlowNodeAsync(EntityIdListDto input)
        {
            List<WorkFlowNode> allBrothers = null;
            foreach (var item in input.List)
            {
                var node = await _workFlowNodeRepository.FirstOrDefaultAsync(item);
                if (node != null)
                {
                    if(allBrothers == null)
                    {
                        allBrothers = await GetAllBrotherNodes(node.WorkflowId);
                    }
                    if (await _workflowDesignService.CanNodeBeRemoveOrEdit(node, allBrothers))
                    {
                        await _workFlowNodeRepository.DeleteAsync(node);
                    }
                    else
                    {
                        throw new UserFriendlyException(RemoveNodeMsg);
                    }
                }
            }
        }

        public async Task SetFlowNodeStatus(SetStatusInput input)
        {
            var list = await _workFlowNodeRepository.GetAllListAsync(item => input.IdList.Contains(item.Id));
            List<WorkFlowNode> allBrothers = null;
            foreach (var item in list)
            {
                if (input.IsActive)
                {
                    item.IsActive = input.IsActive;
                }
                else
                {
                    if (allBrothers == null)
                    {
                        allBrothers = await GetAllBrotherNodes(item.WorkflowId);
                    }
                    if (await _workflowDesignService.CanNodeBeRemoveOrEdit(item, allBrothers))
                    {
                        item.IsActive = input.IsActive;
                    }
                    else
                    {
                        throw new UserFriendlyException(RemoveNodeMsg);
                    }
                }
            }
        }

        public async Task SwapFlowNodeSortAsync(SwapSortNumberInput input)
        {
            var idList = input.IdOrderList.Select(c => c.Id).ToList();
            var orderList = input.IdOrderList.Select(c => c.Order).ToList();

            var list = await _workFlowNodeRepository.GetAllListAsync(c => idList.Contains(c.Id));

            foreach (var item in list)
            {
                var index = idList.FindIndex(c => c == item.Id);
                if (index != -1)
                {
                    item.Order = orderList[index];
                    //await _workflowDesignService.UpdateWorkFlowNodeAsync(item);
                }
            }
        }
        #endregion

        #region WorkFlowPaperListCtrl
        public async Task<CreateOrUpdateListCtrlDto> GetListCtrlConfigAsync(EntityDto<Guid> input)
        {
            var entity = await _workFlowPaperListCtrlRepository.FirstOrDefaultAsync(item => item.Id == input.Id);
            if (entity != null)
            {
                return ObjectMapper.Map<CreateOrUpdateListCtrlDto>(entity);
            }
            return null;
        }

        public async Task CreateOrUpdateListCtrlAsync(CreateOrUpdateListCtrlDto input)
        {
            if(input.Id != null)
            {
                var entity = await _workFlowPaperListCtrlRepository.FirstOrDefaultAsync(item => item.Id == input.Id);
                if (entity != null)
                {
                    ObjectMapper.Map(input, entity);
                    //await _workFlowPaperListCtrlRepository.UpdateAsync(entity);
                }
            }
            else
            {
                var entity = ObjectMapper.Map<WorkFlowPaperListCtrl>(input);
                entity.Id = Guid.NewGuid();
                await _workFlowPaperListCtrlRepository.InsertAsync(entity);
            }
        }

        public async Task<PagedResultDto<PagedListCtrlDto>> GetPagedListCtrlAsync(PagedSortedAndFilteredInputDto input)
        {
            var query = _workFlowPaperListCtrlRepository.GetAll().OrderByDescending(t => t.CreationTime);
            var count = await query.CountAsync();
            var list = await query.PageBy(input).ToListAsync();

            return new PagedResultDto<PagedListCtrlDto>(count, ObjectMapper.Map<List<PagedListCtrlDto>>(list));
        }

        #endregion

        /// <summary>
        /// 用于流程设计中的部门绑定
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<WorkFlowSelectUnitsDto> GetFilterUnitsAsync(FilterUnitInput input)
        {
            var entity = await _workFlowRepository.FirstOrDefaultAsync(input.WorkFlowId);

            if (entity != null)
            {
                if (!entity.UnitIdList.IsNullOrWhiteSpace())
                {
                    var result = new WorkFlowSelectUnitsDto();
                    var arr = entity.UnitIdList.Split(",".ToCharArray()).ToList();

                    var unitCache = await _userAndUnitFinder.GetAllUnitCacheAsync();

                    var units  = unitCache.Where(item => arr.Contains(item.Id.ToString()))
                        .Select(unit => new UnitSelectionData
                        {
                            Id = unit.Id,
                            Code = unit.Code,
                            Name = unit.Name,
                            DisplayName = unit.DisplayName,
                            ParentId = unit.ParentId,
                            Level = unit.Level,
                            Order = unit.Order
                        });

                    var list = await _userAndUnitFinder.GetUnitsWithTheirParents(units);
                    result.UnitIds = arr;
                    result.UnitList = new List<SimpleOrganinzationUnitDto>();
                    list.ForEach(item =>
                    {
                        result.UnitList.Add(new SimpleOrganinzationUnitDto
                        {
                            Code = item.Code,
                            DisplayName = item.Name,
                            Id = item.Id,
                            Order = item.Order,
                            ParentId = item.ParentId
                        });
                    });
                    return result;
                }
            }
            return null;
        }
    }
}
